package com.unionftech.common.webview.view

import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.animation.ValueAnimator
import android.content.Context
import android.content.res.Resources
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.util.AttributeSet
import android.util.TypedValue
import android.view.animation.DecelerateInterpolator
import android.view.animation.LinearInterpolator
import android.widget.FrameLayout
import androidx.annotation.ColorInt
import com.unionftech.common.webview.callback.BaseProgressSpec

class WebProgressBar @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr), BaseProgressSpec {
    companion object {
        /**
         * 默认匀速动画最大的时间
         */
        const val MAX_UNIFORM_SPEED_DURATION = 5 * 1000

        /**
         * 默认加速后减速动画最大时长
         */
        const val MAX_DECELERATE_SPEED_DURATION = 600

        /**
         * 结束动画时长 Fade out
         */
        const val DO_END_ANIMATION_DURATION = 300

        /**
         * 当前匀速动画最大的时长
         */
        var CURRENT_MAX_UNIFORM_SPEED_DURATION = MAX_UNIFORM_SPEED_DURATION

        /**
         * 当前加速后减速动画最大时长
         */
        var CURRENT_MAX_DECELERATE_SPEED_DURATION = MAX_DECELERATE_SPEED_DURATION

        /**
         * 当前进度条的状态
         */
        private var CUR_STATE = 0
        const val UN_START = 0
        const val STARTED = 1
        const val FINISH = 2

        /**
         * 进度条的默认高度
         */
        var WEB_PROGRESS_DEFAULT_HEIGHT = 3

    }

    /**
     * 进度条颜色
     */
    private var mColor = 0

    /**
     * 进度条画笔
     */
    private var mPaint: Paint = Paint()

    /**
     * 进度条动画
     */
    private var mAnimator: Animator? = null

    /**
     * 控件的宽度
     */
    private var mTargetWidth = 0

    /**
     * 当前进度
     */
    private var currentProgress = 0f

    private var target = 0f

    /**
     * 动画执行回调，刷新进度条进度
     */
    private val mAnimatorUpdateListener = ValueAnimator.AnimatorUpdateListener { animation ->
        val value = animation.animatedValue as Float
        currentProgress = value
        this.invalidate()
    }

    /**
     * 动画执行完成回调
     */
    private val mAnimatorListenerAdapter = object : AnimatorListenerAdapter() {
        override fun onAnimationEnd(animation: Animator) {
            doEnd()
        }
    }


    init {
        init(context)
    }

    private fun init(context: Context) {
        mColor = Color.parseColor("#c15d3e")
        mPaint.isAntiAlias = true
        mPaint.color = mColor
        mPaint.isDither = true
        mPaint.strokeCap = Paint.Cap.SQUARE
        mTargetWidth = context.resources.displayMetrics.widthPixels
        WEB_PROGRESS_DEFAULT_HEIGHT = dp2px(2.5f)
    }

    private fun dp2px(dp: Float): Int {
        return TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_DIP,
            dp, Resources.getSystem().displayMetrics
        ).toInt()
    }

    fun setColor(@ColorInt color: Int) {
        mColor = color
        mPaint.color = mColor
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        val widthMode = MeasureSpec.getMode(widthMeasureSpec)
        val heightMode = MeasureSpec.getMode(heightMeasureSpec)
        var width = MeasureSpec.getSize(widthMeasureSpec)
        var height = MeasureSpec.getSize(heightMeasureSpec)
        if (widthMode == MeasureSpec.AT_MOST) {
            val widthPixels = context.resources.displayMetrics.widthPixels
            width = if (width <= widthPixels) width else widthPixels
        }
        if (heightMode == MeasureSpec.AT_MOST) {
            height = WEB_PROGRESS_DEFAULT_HEIGHT
        }
        setMeasuredDimension(width, height)
    }

    override fun onDraw(canvas: Canvas) {

    }

    override fun dispatchDraw(canvas: Canvas) {
        canvas.drawRect(0f, 0f, currentProgress * 1.0f / this.width * 100, height.toFloat(), mPaint)
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        mTargetWidth = measuredWidth
        val screenWidth = context.resources.displayMetrics.widthPixels
        if (mTargetWidth >= screenWidth) {
            CURRENT_MAX_DECELERATE_SPEED_DURATION = MAX_DECELERATE_SPEED_DURATION
            CURRENT_MAX_UNIFORM_SPEED_DURATION = MAX_UNIFORM_SPEED_DURATION
        } else {
            val rate = mTargetWidth / screenWidth * 1.0f
            CURRENT_MAX_UNIFORM_SPEED_DURATION = (MAX_UNIFORM_SPEED_DURATION * rate).toInt()
            CURRENT_MAX_DECELERATE_SPEED_DURATION = (MAX_DECELERATE_SPEED_DURATION * rate).toInt()
        }
    }

    override fun show() {
        if (visibility == GONE) {
            visibility = VISIBLE
            currentProgress = 0f
            startAnim(false)
        }
    }


    override fun hide() {
        CUR_STATE = FINISH
    }

    override fun reset() {
        currentProgress = 0f
        mAnimator?.run {
            if (isStarted) {
                cancel()
            }
        }
    }

    override fun setProgress(progress: Int) {
        updateProgress(progress.toFloat())
    }

    fun updateProgress(progress: Float) {
        if (visibility == GONE) {
            visibility = VISIBLE
        }
        if (progress < 95f) {
            return
        }
        if (CUR_STATE != FINISH) {
            startAnim(true)
        }
    }

    private fun startAnim(isFinish: Boolean) {
        val value = if (isFinish) 100f else 95f
        mAnimator?.run {
            if (isStarted) {
                cancel()
            }
        }
        currentProgress = if (currentProgress == 0f) 0.00000001f else currentProgress
        //进度为0-94，匀速动画
        if (!isFinish) {
            val mAnimator = ValueAnimator.ofFloat(currentProgress, value)
            val residue = 1f - currentProgress / 100 - 0.05f
            //使用匀速插值器
            mAnimator.interpolator = LinearInterpolator()
            mAnimator.duration = (residue * CURRENT_MAX_UNIFORM_SPEED_DURATION).toLong()
            mAnimator.addUpdateListener(mAnimatorUpdateListener)
            mAnimator.start()
            this.mAnimator = mAnimator
        } else {
            //进度大于等于95后执行透明减速动画
            var segment95Animator: ValueAnimator? = null
            if (currentProgress < 95f) {
                segment95Animator = ValueAnimator.ofFloat(currentProgress, 95f)
                val residue = 1f - currentProgress / 100f - 0.05f
                segment95Animator.duration =
                    (residue * CURRENT_MAX_DECELERATE_SPEED_DURATION).toLong()
                //使用减速插值器
                segment95Animator.interpolator = DecelerateInterpolator()
                segment95Animator.addUpdateListener(mAnimatorUpdateListener)
            }
            //透明度动画
            val alphaAnimation = ObjectAnimator.ofFloat(this, "alpha", 1f, 0f)
            alphaAnimation.duration = DO_END_ANIMATION_DURATION.toLong()
            //动画刷新进度从95-100
            val mValueAnimator = ValueAnimator.ofFloat(95f, 100f)
            mValueAnimator.duration = DO_END_ANIMATION_DURATION.toLong()
            mValueAnimator.addUpdateListener(mAnimatorUpdateListener)
            var mAnimatorSet = AnimatorSet()
            mAnimatorSet.playTogether(alphaAnimation, mValueAnimator)
            if (segment95Animator != null) {
                val nextAnimatorSet = AnimatorSet()
                //执行alpha动画并刷新进度，然后执行减速动画
                nextAnimatorSet.play(mAnimatorSet).after(segment95Animator)
                mAnimatorSet = nextAnimatorSet
            }
            mAnimatorSet.addListener(mAnimatorListenerAdapter)
            mAnimatorSet.start()
            this.mAnimator = mAnimatorSet

        }
        CUR_STATE = STARTED
        target = value
    }


    /**
     * 动画执行完成，将进度条恢复初始值
     */
    private fun doEnd() {
        if (CUR_STATE == FINISH && currentProgress == 100f) {
            visibility = GONE
            currentProgress = 0f
            this.alpha = 1f
        }
        CUR_STATE = UN_START
    }

    /**
     * 释放动画资源
     */
    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
        mAnimator?.also {
            if (it.isStarted) {
                it.cancel()
                mAnimator = null
            }
        }
    }
}